import java.util.ArrayList;
import java.util.HashMap;

public class Analyse {
    private static ArrayList<String> strings;
    private static String targetStr;
    private static int index = 0;
    private static int line = 0;
    
    /*public Analyse(String str) {
        this.targetStr = str;
    }*/
    
    public Analyse(ArrayList<String> strings) {
        this.strings = strings;
        this.targetStr = strings.get(0);
    }
     
    static char getChar() {
        if (index < targetStr.length()) {
            index++;
            return targetStr.charAt(index - 1);
        } else if (line < strings.size() - 1) {
            line++;
            targetStr = strings.get(line);
            index = 1;
            return targetStr.charAt(index - 1);
        } else if (line < strings.size()) {
            line++;
        }
        return ' ';
    }
    
    public ArrayList<Pairs> analyseTxt() {
        ArrayList<Pairs> resultTokens = new ArrayList<>();
        while (line < strings.size()) {
            Pairs pairs = new Pairs(null, "");
            String token = "";
            char ch = getChar();
            while ((ch == ' ' || ch == '\n' || ch == '\t') && index < targetStr.length()) {
                ch = getChar();
            }
            if (ch == '/') {        //注释以及'/'
                ch = getChar();
                if (ch == '/') {
                    while (ch != '\n') {
                        ch = getChar();
                    }
                } else if (ch == '*') {
                    ch = getChar();
                    while (true) {
                        while (ch != '*') {
                            ch = getChar();
                        }
                        ch = getChar();
                        if (ch == '/') {
                            break;
                        }
                    }
                } else {
                    index--;
                    token += '/';
                    pairs.setKind(Pairs.Kind.DIV);
                    pairs.setToken(token);
                    pairs.setLine(line + 1);
                    resultTokens.add(pairs);
                }
            } else if (ch == '\"') {  //formatString
                token += ch;
                ch = getChar();
                while (ch != '\"') {
                    token += ch;
                    ch = getChar();
                }
                token += ch;
                pairs.setKind(Pairs.Kind.STRCON);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (isLetter(ch)) {    //字符
                while (isLetter(ch) || isDigit(ch)) {
                    token += ch;
                    ch = getChar();
                }
                index--;
                Pairs.Kind resultValue = reserver(token);
                if (resultValue != null) {
                    pairs.setKind(resultValue);
                    pairs.setToken(token);
                    pairs.setLine(line + 1);
                    resultTokens.add(pairs);
                } else {
                    pairs.setKind(Pairs.Kind.IDENFR);
                    pairs.setToken(token);
                    pairs.setLine(line + 1);
                    resultTokens.add(pairs);
                }
            } else if (isDigit(ch)) {   //Intconst
                while (isDigit(ch)) {
                    token += ch;
                    ch = getChar();
                }
                index--;
                int num = transNum(token);
                pairs.setKind(Pairs.Kind.INTCON);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (ch == '!') {
                token += ch;
                ch = getChar();
                if (ch == '=') {
                    token += ch;
                    pairs.setKind(Pairs.Kind.NEQ);
                    pairs.setToken(token);
                    pairs.setLine(line + 1);
                    resultTokens.add(pairs);
                } else {
                    index--;
                    pairs.setKind(Pairs.Kind.NOT);
                    pairs.setToken(token);
                    pairs.setLine(line + 1);
                    resultTokens.add(pairs);
                }
            } else if (ch == '*') {
                token += ch;
                pairs.setKind(Pairs.Kind.MULT);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (ch == '%') {
                token += ch;
                pairs.setKind(Pairs.Kind.MOD);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (ch == '<') {
                token += ch;
                ch = getChar();
                if (ch == '=') {
                    token += ch;
                    pairs.setKind(Pairs.Kind.LEQ);
                    pairs.setToken(token);
                    pairs.setLine(line + 1);
                    resultTokens.add(pairs);
                } else {
                    index--;
                    pairs.setKind(Pairs.Kind.LSS);
                    pairs.setToken(token);
                    pairs.setLine(line + 1);
                    resultTokens.add(pairs);
                }
            } else if (ch == '>') {
                token += ch;
                ch = getChar();
                if (ch == '=') {
                    token += ch;
                    pairs.setKind(Pairs.Kind.GEQ);
                    pairs.setToken(token);
                    pairs.setLine(line + 1);
                    resultTokens.add(pairs);
                } else {
                    index--;
                    pairs.setKind(Pairs.Kind.GRE);
                    pairs.setToken(token);
                    pairs.setLine(line + 1);
                    resultTokens.add(pairs);
                }
            } else if (ch == '=') {
                token += ch;
                ch = getChar();
                if (ch == '=') {
                    token += ch;
                    pairs.setKind(Pairs.Kind.EQL);
                    pairs.setToken(token);
                    pairs.setLine(line + 1);
                    resultTokens.add(pairs);
                } else {
                    index--;
                    pairs.setKind(Pairs.Kind.ASSIGN);
                    pairs.setToken(token);
                    pairs.setLine(line + 1);
                    resultTokens.add(pairs);
                }
            } else if (ch == ';') {
                token += ch;
                pairs.setKind(Pairs.Kind.SEMICN);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (ch == ',') {
                token += ch;
                pairs.setKind(Pairs.Kind.COMMA);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (ch == '(') {
                token += ch;
                pairs.setKind(Pairs.Kind.LPARENT);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (ch == ')') {
                token += ch;
                pairs.setKind(Pairs.Kind.RPARENT);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (ch == '[') {
                token += ch;
                pairs.setKind(Pairs.Kind.LBRACK);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (ch == ']') {
                token += ch;
                pairs.setKind(Pairs.Kind.RBRACK);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (ch == '{') {
                token += ch;
                pairs.setKind(Pairs.Kind.LBRACE);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (ch == '}') {
                token += ch;
                pairs.setKind(Pairs.Kind.RBRACE);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (ch == '+') {
                token += ch;
                pairs.setKind(Pairs.Kind.PLUS);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (ch == '-') {
                token += ch;
                pairs.setKind(Pairs.Kind.MINU);
                pairs.setToken(token);
                pairs.setLine(line + 1);
                resultTokens.add(pairs);
            } else if (ch == '&') {
                token += ch;
                ch = getChar();
                if (ch == '&') {
                    token += ch;
                    pairs.setKind(Pairs.Kind.AND);
                    pairs.setToken(token);
                    pairs.setLine(line + 1);
                    resultTokens.add(pairs);
                }
            } else if (ch == '|') {
                token += ch;
                ch = getChar();
                if (ch == '|') {
                    token += ch;
                    pairs.setKind(Pairs.Kind.OR);
                    pairs.setToken(token);
                    pairs.setLine(line + 1);
                    resultTokens.add(pairs);
                }
            }
        }
        return resultTokens;
    }
    
    public boolean isLetter(char ch) {
        return ch == '_' || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
    }
    
    public boolean isDigit(char ch) {
        return ch >= '0' && ch <= '9';
    }
    
    public Pairs.Kind reserver(String s) {
        if (s.equals("main")) {
            return Pairs.Kind.MAINTK;
        } else if (s.equals("const")) {
            return Pairs.Kind.CONSTTK;
        } else if (s.equals("int")) {
            return Pairs.Kind.INTTK;
        } else if (s.equals("break")) {
            return Pairs.Kind.BREAKTK;
        } else if (s.equals("continue")) {
            return Pairs.Kind.CONTINUETK;
        } else if (s.equals("if")) {
            return Pairs.Kind.IFTK;
        } else if (s.equals("else")) {
            return Pairs.Kind.ELSETK;
        } else if (s.equals("while")) {
            return Pairs.Kind.WHILETK;
        } else if (s.equals("getint")) {
            return Pairs.Kind.GETINTTK;
        } else if (s.equals("printf")) {
            return Pairs.Kind.PRINTFTK;
        } else if (s.equals("return")) {
            return Pairs.Kind.RETURNTK;
        } else if (s.equals("void")) {
            return Pairs.Kind.VOIDTK;
        } else {
            return null;
        }
    }
    
    public int transNum(String token) {
        return Integer.parseInt(token);
    }
}
